package task

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/gin-gonic/gin"
	"scheduling/model"
	"scheduling/plugin"
	"sort"
	"strconv"
	"strings"
)

type Perms struct {
	signInfo model.SignKeys //加密密钥
	permType string         //认证方式
	signType string         //加密密钥
	argName  string         //token名称
}

func NewPerms(signInfo model.SignKeys, permType string, signType string, argName string) *Perms {
	m := new(Perms)
	m.signInfo = signInfo
	m.permType = permType
	m.signType = signType
	m.argName = argName
	return m
}

func (m *Perms) Certification(c *gin.Context, data map[string]interface{}) bool {
	switch m.permType {
	case "jwt":
		return m.jwtAuth(c, data)
	case "wx":
		return m.wxAuth(data)
	case "wxv3":
		return m.wxv3Auth(data)
	}
	return false
}

func (m *Perms) jwtAuth(c *gin.Context, data map[string]interface{}) bool {
	tokenStr, _ := c.Cookie(m.argName)
	if tokenStr == "" {
		tokenStr = data[m.argName].(string)
	}
	return plugin.NewJwtUtils(m.signInfo.PrivateKey.String).Validate(tokenStr)
}

func (m *Perms) wxAuth(data map[string]interface{}) bool {
	sign := data[m.argName]
	if sign == nil {
		return false
	}
	sign = strings.ToUpper(sign.(string))
	keys := make([]string, len(data))
	i := 0
	for k, _ := range data {
		keys[i] = k
		i++
	}
	sort.Strings(keys)
	fmt.Println(keys)
	buf := bytes.Buffer{}
	delete(data, m.argName)
	for i, k := range keys {
		val := data[k]
		if val == nil {
			continue
		}
		buf.WriteString(k)
		buf.WriteString("=")
		if v, ok := val.(string); ok {
			buf.WriteString(v)
		} else if v, ok := val.(int64); ok {
			buf.WriteString(strconv.Itoa(int(v)))
		} else if v, ok := val.(int); ok {
			buf.WriteString(strconv.Itoa(v))
		}
		if i+1 == len(data) {
			buf.WriteString("&")
		}
	}
	h := md5.New()
	h.Write(buf.Bytes())
	if sign == strings.ToUpper(hex.EncodeToString(h.Sum(nil))) {
		return true
	}
	return false
}

func (m *Perms) wxv3Auth(data map[string]interface{}) bool {
	return false
}
